#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === ADB Database Opened ===
function adbdatabase()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbdatabase </data/.../sqlite.db> (Android sqlite3 database opener)';
    echo '';
    return;
  fi;

  # Variables
  local name;
  local path;

  # Pull and open
  adbro;
  path=${1};
  name=$(basename "${path}");
  adb pull "${path}";
  sqlite3 "${name}";
}

# === Sepolicies Extractor ===
function sepaud()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: sepaud <logs_file> [context_search] (Logs sepolicy analyzer)';
    echo '';
    return;
  fi;

  # Logs sepolicy analyzer
  echo '';
  grep -a "avc.*denied .*${2}" "${1}";
  grep -a 'does not have a SELinux domain defined' "${1}";
  grep -a "avc.*denied .*${2}" "${1}" | audit2allow -p sepolicy;
  echo '';
}

# === Sepolicies Message Extractor ===
function sepmsg()
{
  # Fallback to sepaud without a context
  if [ -z "${2}" ]; then
    sepaud "${1}";
  fi;

  # Usage
  if [ ! -f "${1}" ]; then
    echo '';
    echo ' Usage: sepmsg <logs_file> <context> [grep] (Logs sepolicy message extractor)';
    echo '';
    return;
  fi;

  # Run the logs sepolicy analyzer
  sepaud "${1}" "${2}:" | grep "${3}";

  # Logs sepolicy message extractor
  echo '';
  grep -a "avc.*denied.*scontext=u:r:${2}:s0" "${1}" \
      | grep "${3}" \
      | sed 's/.*avc: /avc: /g' \
      | sed 's/ permissive=.*//g' \
      | sed 's/\(comm\|ino\|ioctlcmd\|pid\)=\("\|\)[^ ]*\("\|\) //g' \
      | sed 's/ path="\(socket\|pipe\):\[[^ ]*\]"/ path="\1:..."/g' \
      | sort \
      | uniq \
      | fold -w 70 -s \
      | sed 's/^/    /g' \
      | sed 's/.*avc:[ ]\{1,2\}denied[ ]\{1,2\}/ * denied /g';
  echo '';
}

# === ADB Intents ===
alias adbintents='adb shell dumpsys package r > intents.txt';

# === ADB Camera Enabled / Launcher ===
function adbcamera()
{
  # Usage: adbcamera (Enable and launch camera applications)

  # Enable and launch camera applications
  adb shell pm enable com.android.camera2/com.android.camera.CameraLauncher;
  adb shell pm enable com.google.android.GoogleCamera/com.android.camera.CameraLauncher;
  adb shell "am start -a android.media.action.IMAGE_CAPTURE";
}

# === ADB Kill Process ===
function adbkp()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbkp <process_name> (Kill process by name)';
    echo '';
    return;
  fi;

  # Kill process by name
  adbwait;
  adb root;
  adbwait;
  adb shell ps | grep "${1}";
  pid=$(adb shell ps | grep "${1}" | awk '{ print $2 }');
  adb shell kill "${pid}";
}

# === ADB Crash Debuggers ===
function adbpk()
{
  # Usage: adbpk (Android mediaserver debug logger)

  # Variables
  local pid;

  # Android mediaserver debug logger
  pid=$(adb shell ps | grep mediaserver | awk '{ print $2 }');
  adb root;
  adbwait;
  adb logcat -c;
  adb shell kill "${pid}";
  adb shell ps | grep mediaserver;
  sleep 2;
  adbl;
}
function adbms()
{
  # Usage: adbms (Android mediaserver debug stracer)

  # Android mediaserver debug stracer
  pid=$(adb shell ps | grep mediaserver | awk '{ print $2 }');
  adb root;
  adbwait;
  adb logcat -c;
  adb shell kill "${pid}";
  pid=$(adb shell ps | grep mediaserver | awk '{ print $2 }');
  adb shell strace -p "${pid}";
}

function adblibs() { adb shell grep -air "${1}" "${2:-/system/lib/}"; }
alias ndkstack='ndk-stack -sym "${ANDROID_DEV_DRIVE}/out/target/product/huashan/symbols" -dump';
function adbwtch() { adbr; while true; do adb shell cat "${1}"; done; }

function adbdu()
{
  # Usage: adbdu (Android /data/ sizes study)

  # Variables
  local tmp;

  # Android /data/ sizes study
  tmp=$(mktemp);
  adbsu 'du /data/ | sort -hr' > "${tmp}";
  fileedit "${tmp}";
}

# === ADB Property Radio Logs ===
function adbpropradiolog()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbpropradiolog <value> (Radio debug property overrider)';
    echo '';
    return;
  fi;

  # Variable
  local cmd;
  local property=persist.radio.adb_log_on;
  echo '';

  # Get property
  cmd="adb shell getprop ${property}";
  echo -n " ${cmd} > ";
  ${cmd};

  # Set property
  cmd="adb shell setprop ${property} ${1}";
  echo " ${cmd}";
  adb root;
  ${cmd};

  # Get property
  cmd="adb shell getprop ${property}";
  echo -n " ${cmd} > ";
  ${cmd};
  echo '';
}

# === ADB Alsa Reader ===
function adbalsa()
{
  # Usage: adbalsa (Audio cards advanced study)

  # Audio cards advanced study
  echo -n '' > alsalog;
  adb shell "cat /proc/asound/card0/id" | tee -a alsalog;
  for line in $(adb shell find /proc/asound/card0 -name info); do
    path=$(echo -n "${line}" | tr -dc 'a-zA-Z0-9/');
    echo '' | tee -a alsalog;
    echo "=== ${path} ===" | tee -a alsalog;
    adb shell "cat ${path}" | tee -a alsalog;
    if [[ "${path}" == *'sub'* ]]; then
      folder=$(dirname "${path}");
      adb shell "cat ${folder}/hw_params" | tee -a alsalog;
      adb shell "cat ${folder}/status" | tee -a alsalog;
      adb shell "cat ${folder}/sw_params" | tee -a alsalog;
    fi;
  done;
  adb shell "cat /proc/asound/devices" | tee -a alsalog;
  adb shell "cat /proc/asound/pcm" | tee -a alsalog;
  adb shell "cat /proc/asound/timers" | tee -a alsalog;
}

# === ADB TinyMix Helper ===
function adbtinymix()
{
  # Usage: adbtinymix (Run tinymix on the device)

  # Variables
  local tinymix_exists;

  # Detect tinymix requirement
  tinymix_exists=$(adbsu 'if [ ! -e /system/bin/tinymix ]; then echo false; fi;');
  if [ ! -z "${tinymix_exists}" ]; then
    adb push "${ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_TINYMIX}" /sdcard/tinymix;
    adbsur 'cp /sdcard/tinymix /system/bin/tinymix;
            rm /sdcard/tinymix;
            chmod 777 /system/bin/tinymix';
    echo '';
  fi;

  # Launch tinymix
  adbsu '/system/bin/tinymix';
}

# === ADB Manifest.xml Editor ===
function adbeditmanifest()
{
  # Usage: adbeditmanifest (Edit adb /system/vendor/manifest.xml file)

  # Edit adb /system/vendor/manifest.xml file
  adbedit /system/vendor/manifest.xml;
}

# === ADB Inputs Reader ===
function adbinputs()
{
  # Usage: adbinputs (Dump all input devices)

  #grep . /sys/class/input/event*/device/name
  #adbs hexdump -C /dev/input/event7
  command='cat /proc/bus/input/devices';
  echo '';
  echo "adb shell ${command}";
  echo '';
  adb shell "${command}";
}

# === ADB Events Reader ===
function adbreadevents()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbreadevents <event_number> (Read input events)';
    echo '';
    return;
  fi;

  # Read input events
  adb shell od -x "/dev/input/${1}" \
   | awk -Wposix '{ if ($7) printf(" Key %4d - State %4d\n", "0x" $7, "0x" $8) }';
}
